//@version=6
indicator(title = "VB Sigma Smart Momentum Indicator", shorttitle = "VBSSMI", format = format.price, precision = 2)

//──────────────────────────────────────────────────────────────
// 1. MCDX: Institutional / Retail / Trader Flows
//──────────────────────────────────────────────────────────────

//---------------------------
// MCDX Settings
//---------------------------
groupMCDX = "MCDX Settings"

displayIF     = input.bool(true,  "Display MCDX",                 group = groupMCDX)
mcdx_source   = close
mcdx_length   = input.string("Auto", "MCDX Length", options = ["Auto", "50-day", "100-day", "Manual Input"], group = groupMCDX)
manual_len    = 100

// Legacy SMA & show toggles (currently not exposed / minimal use)
pc_show       = false
fc_show       = false
lc_show       = false
sma_pc_len    = 10
sma_pc_show   = false
sma_fc_len    = 10
sma_fc_show   = false
sma_lc_len    = 10
sma_lc_show   = true

//---------------------------
// MCDX Helper Functions
//---------------------------
fmcdx_hoh(X, N) =>
    ta.highest(X, N)

fmcdx_lol(X, N) =>
    ta.lowest(X, N)

fmcdx_range(H, L, N) =>
    ta.highest(H, N) - ta.lowest(L, N)

fmcdx_avg(H, L, N) =>
    (ta.highest(H, N) + ta.lowest(L, N)) / 2.0

fmcdx_pc(X, N) =>
    rangeFn = ta.highest(high, N) - ta.lowest(low, N)
    rangeFn != 0 ? (X - ta.lowest(low, N)) / rangeFn * 100.0 : 0.0

fmcdx_fc(X, N) =>
    rangeFn = ta.highest(high, N) - ta.lowest(low, N)
    rangeFn != 0 ? 100.0 - (ta.highest(high, N) - X) / rangeFn * 100.0 + 25.0 : 0.0

fr(X, N) =>
    rangeFn = ta.highest(high, N) - ta.lowest(low, N)
    rangeFn != 0 ? (X - ta.lowest(low, N)) / rangeFn * 100.0 : 0.0

fY(X, N, M) =>
    alpha = M / N
    beta  = 0.0
    beta := nz(beta[1]) - nz(X[N]) + X
    gamma = 0.0
    gamma := na(X[N]) ? na : beta / N
    lamda = 0.0
    lamda := na(lamda[1]) ? beta : alpha * X + (1 - alpha) * nz(lamda[1])
    lamda

//---------------------------
// MCDX Source & Effective Length
//---------------------------
mcdx_src = mcdx_source

// Auto length based on bar_index, capped at 100
auto_len = 3
for i = 3 to 100 by 1
    if bar_index == i
        auto_len := i
        break
    if bar_index >= 100
        auto_len := 100
        break

int mcdx_len = 3
mcdx_len :=
     mcdx_length == "Auto"         ? auto_len :
     mcdx_length == "50-day"       ? 50 :
     mcdx_length == "100-day"      ? 100 :
     mcdx_length == "Manual Input" ? manual_len :
                                     3

// Generic shorthand
X = mcdx_src
N = mcdx_len
H = high
L = low
C = close
O = open

mcdx_hoh_val   = fmcdx_hoh(H, N)
mcdx_lol_val   = fmcdx_lol(L, N)
mcdx_range_val = fmcdx_range(H, L, N)
mcdx_avg_val   = fmcdx_avg(H, L, N)

//---------------------------
// Locked Chips (Retailer Flow)
//---------------------------
lc = int(na)

for i = 3 to 100 by 1
    if bar_index == i - 1 and mcdx_length == "Auto"
        lc := 100
        break
    if bar_index >= 100 and mcdx_length == "Auto"
        lc := 100
        break
    if bar_index >= 50 - 1 and mcdx_length == "50-day"
        lc := 100
        break
    if bar_index >= 100 - 1 and mcdx_length == "100-day"
        lc := 100
        break
    if bar_index >= manual_len - 1 and mcdx_length == "Manual Input"
        lc := 100
        break

locked_chips = lc
plot(
     displayIF ? locked_chips : na,
     title     = "Retailer Flow",
     color     = color.new(#39FF14, 0),
     linewidth = 10,
     style     = plot.style_columns)

//---------------------------
// Float Chips (Trader Zone Flow)
//---------------------------
sma20       = ta.sma(mcdx_src, 20)
mcdx_avg50  = fmcdx_avg(H, L, 50)
fc          = fmcdx_fc(X, N)

// Four conditions for float chips (depending on length >= 100 or not)
fc_1 = mcdx_len >= 100 ?
           C > O and L > sma20 and L > mcdx_avg_val and L > mcdx_avg50 :
           C > O and L > sma20 and L > mcdx_avg_val

fc_2 = mcdx_len >= 100 ?
           C > O and C > sma20 and C > mcdx_avg_val and C > mcdx_avg50 :
           C > O and C > sma20 and C > mcdx_avg_val

fc_3 = mcdx_len >= 100 ?
           C > sma20 and O > mcdx_avg_val and O > mcdx_avg50 and C > mcdx_avg50 and C > mcdx_avg_val :
           C > sma20 and O > mcdx_avg_val and C > mcdx_avg_val

fc_4 = mcdx_len >= 100 ?
           C >= O and H > mcdx_avg_val and C > mcdx_avg50 :
           C >= O and H > mcdx_avg_val and C > mcdx_avg_val

fc_all = fc_1 or fc_2 or fc_3 or fc_4 ? 100.0 : fc

float_chips =
     fc_all > 100 ? 100 :
     fc_all <   0 ?   0 :
                   fc_all

plot(
     displayIF ? float_chips : na,
     title     = "Trader Zone Flow",
     color     = color.new(#FFFF00, 0),
     linewidth = 10,
     style     = plot.style_columns)

//---------------------------
// Profitable Chips (Institutional / Bankers Flow)
//---------------------------
pc_1 = fmcdx_pc(X, N)
pc_2 = mcdx_range_val != 0 ? (X - mcdx_avg_val) / mcdx_range_val * 100.0 : 0.0
pc_3 = (pc_1 + pc_2) / 2.0 + 25.0

profit_chips =
     pc_3 <   0 ?   0 :
     pc_3 > 100 ? 100 :
                  pc_3

sma_pc   = ta.sma(profit_chips, sma_pc_len)
pc_color = profit_chips >= sma_pc ? color.new(#EB4C42, 10) : color.new(#FFB7C5, 0)

plot(
     displayIF ? profit_chips : na,
     title     = "Institutional/Bankers Flow",
     color     = pc_color,
     linewidth = 10,
     style     = plot.style_columns)

//──────────────────────────────────────────────────────────────
// 2. Donchian Channel Heat Columns
//──────────────────────────────────────────────────────────────

groupDonchian = "Donchain Settings"
displayDC     = input.bool(true, "Display Donchian", group = groupDonchian)

dlen       = 20
i_posColor = color.rgb(76, 255, 255)
i_negColor = color.rgb(237, 74, 252)

// Main Donchian trend: 1 (up) / -1 (down)
dchannel(len) =>
    hh = ta.highest(len)
    ll = ta.lowest(len)
    trend = 0
    trend := close > hh[1] ? 1 : close < ll[1] ? -1 : nz(trend[1])
    trend

// Color by local trend & main trend
dchannelalt(len, maintrend) =>
    hh = ta.highest(len)
    ll = ta.lowest(len)
    trend = 0
    trend := close > hh[1] ? 1 : close < ll[1] ? -1 : nz(trend[1])

    maintrend == 1 ?        color.rgb(0, 217, 255, 80) :     maintrend == -1 ?        (trend == -1 ? color.rgb(247, 0, 255, 80) : color.rgb(67, 22, 68, 80)) :        na

maintrend = dchannel(dlen)

// Stack of vertical columns (visual regime bands)
plot(displayDC ?  5 : na, color = dchannelalt(dlen - 0, maintrend), style = plot.style_columns, histbase =  0)
plot(displayDC ? 10 : na, color = dchannelalt(dlen - 1, maintrend), style = plot.style_columns, histbase =  5)
plot(displayDC ? 15 : na, color = dchannelalt(dlen - 2, maintrend), style = plot.style_columns, histbase = 10)
plot(displayDC ? 20 : na, color = dchannelalt(dlen - 3, maintrend), style = plot.style_columns, histbase = 15)
plot(displayDC ? 25 : na, color = dchannelalt(dlen - 4, maintrend), style = plot.style_columns, histbase = 20)
plot(displayDC ? 30 : na, color = dchannelalt(dlen - 5, maintrend), style = plot.style_columns, histbase = 25)
plot(displayDC ? 35 : na, color = dchannelalt(dlen - 6, maintrend), style = plot.style_columns, histbase = 30)
plot(displayDC ? 40 : na, color = dchannelalt(dlen - 7, maintrend), style = plot.style_columns, histbase = 35)
plot(displayDC ? 45 : na, color = dchannelalt(dlen - 8, maintrend), style = plot.style_columns, histbase = 40)
plot(displayDC ? 50 : na, color = dchannelalt(dlen - 9, maintrend), style = plot.style_columns, histbase = 45)

//──────────────────────────────────────────────────────────────
// 3. Banker Flow Model
//──────────────────────────────────────────────────────────────

groupBanker = "Bankers Settings"
displayBF   = input.bool(true, "Display Banker Flow", group = groupBanker)

// Helper functions for banker logic
xrf(values, length) =>
    r_val = float(na)
    if length >= 1
        for i = 0 to length by 1
            if na(r_val) or not na(values[i])
                r_val := values[i]
                r_val
    r_val

xsa(src, len, wei) =>
    sumf = 0.0
    ma   = 0.0
    out  = 0.0
    sumf := nz(sumf[1]) - nz(src[len]) + src
    ma   := na(src[len]) ? na : sumf / len
    out  := na(out[1]) ? ma : (src * wei + out[1] * (len - wei)) / len
    out

// Banker "fund flow" trend model
fund_raw = (close - ta.lowest(low, 27)) / (ta.highest(high, 27) - ta.lowest(low, 27)) * 100
fund_1   = xsa(fund_raw, 5, 1)
fund_2   = xsa(fund_1,   3, 1)
fundtrend = (3 * fund_1 - 2 * fund_2 - 50) * 1.032 + 50

// Typical price for banker flow
typ = (2 * close + high + low + open) / 5.0
lol = ta.lowest(low, 34)
hoh = ta.highest(high, 34)

// Banker bull/bear line
bullbearline = ta.ema((typ - lol) / (hoh - lol) * 100.0, 13)

// Entry signal
bankerentry = ta.crossover(fundtrend, bullbearline) and bullbearline < 25

// Plot banker candles
// Yellow: banker entry
plotcandle(
     0, 80, 0, 80,
     color = displayBF and bankerentry ? color.new(color.yellow, 0) : na)

// Green: banker increasing position
plotcandle(
     fundtrend, bullbearline, fundtrend, bullbearline,
     color = displayBF and fundtrend > bullbearline ? color.new(i_posColor, 0) : na)

// White: banker decreasing position
plotcandle(
     fundtrend, bullbearline, fundtrend, bullbearline,
     color = displayBF and fundtrend < xrf(fundtrend * 0.95, 1) ? color.new(color.white, 0) : na)

// Red: banker exit / quit
plotcandle(
     fundtrend, bullbearline, fundtrend, bullbearline,
     color = displayBF and fundtrend < bullbearline ? color.new(i_negColor, 0) : na)

// Blue: weak rebound
plotcandle(
     fundtrend, bullbearline, fundtrend, bullbearline,
     color = displayBF and fundtrend < bullbearline and fundtrend > xrf(fundtrend * 0.95, 1) ? color.new(color.blue, 0) : na)

// Overbought / oversold lines
h1 = hline(80, color = i_negColor,        linestyle = hline.style_dotted)
h2 = hline(20, color = color.yellow,      linestyle = hline.style_dotted)
h3 = hline(10, color = i_posColor,        linestyle = hline.style_dotted)
h4 = hline(90, color = color.fuchsia,     linestyle = hline.style_dotted)

fill(h2, h3, color = color.new(color.yellow,   70))
fill(h1, h4, color = color.new(color.fuchsia,  70))

// Alerts
alertcondition(bankerentry,                                    title = "Alert on Yellow Candle", message = "Yellow Candle!")
alertcondition(fundtrend > bullbearline,                       title = "Alert on Green Candle",  message = "Green Candle!")
alertcondition(fundtrend < xrf(fundtrend * 0.95, 1),           title = "Alert on White Candle",  message = "White Candle!")
alertcondition(fundtrend < bullbearline,                       title = "Alert on Red Candle",    message = "Red Candle!")
alertcondition(fundtrend < bullbearline and fundtrend > xrf(fundtrend * 0.95, 1), title = "Alert on Blue Candle", message = "Blue Candle!")

//──────────────────────────────────────────────────────────────
// 4. Chop Zone Heat Bar (EMA angle proxy)
//──────────────────────────────────────────────────────────────

groupDisplay = "Display Settings"
chopZone     = input.bool(true, "Show Chop Zone", group = groupDisplay)

colorTurquoise_cz   = #26C6DA
colorDarkGreen_cz   = #43A047
colorPaleGreen_cz   = #A5D6A7
colorLime_cz        = #009688
colorDarkRed_cz     = #D50000
colorRed_cz         = #E91E63
colorOrange_cz      = #FF6D00
colorLightOrange_cz = #FFB74D
colorYellow_cz      = #FDD835

source_cz  = close
avg_cz     = hlc3
pi_cz      = math.atan(1) * 4
periods_cz = 30

highestHigh_cz = ta.highest(periods_cz)
lowestLow_cz  = ta.lowest(periods_cz)
span_cz       = 25.0 / (highestHigh_cz - lowestLow_cz) * lowestLow_cz

ema34_cz   = ta.ema(source_cz, 34)
x1_ema34   = 0.0
x2_ema34   = 1.0
y1_ema34   = 0.0
y2_ema34   = (ema34_cz[1] - ema34_cz) / avg_cz * span_cz

c_ema34    = math.sqrt((x2_ema34 - x1_ema34) * (x2_ema34 - x1_ema34) + (y2_ema34 - y1_ema34) * (y2_ema34 - y1_ema34))
emaAngle_1 = c_ema34 != 0 ? math.round(180 * math.acos((x2_ema34 - x1_ema34) / c_ema34) / pi_cz) : 0
emaAngle_cz = y2_ema34 > 0 ? -emaAngle_1 : emaAngle_1

// Angle → color mapping
chopZoneColor_cz =
     emaAngle_cz >= 5        ? colorTurquoise_cz   :
     emaAngle_cz >= 3.57     ? colorDarkGreen_cz   :
     emaAngle_cz >= 2.14     ? colorPaleGreen_cz   :
     emaAngle_cz >= 0.71     ? colorLime_cz        :
     emaAngle_cz <= -5       ? colorDarkRed_cz     :
     emaAngle_cz <= -3.57    ? colorRed_cz         :
     emaAngle_cz <= -2.14    ? colorOrange_cz      :
     emaAngle_cz <= -0.71    ? colorLightOrange_cz :
                               colorYellow_cz

plotshape(
     chopZone ? 1 : na,
     style   = shape.square,
     location= location.bottom,
     color   = chopZoneColor_cz,
     size    = size.auto,
     title   = "Chop Zone",
     editable= true)
